using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.IO;
using System.Xml.Serialization;
using System.Windows.Media;
using System.Windows;
using System.Reflection;
using WMFMetadataReader;
using Toub.MediaCenter.Dvrms.Metadata;
using Level65.ClipShow;

namespace Level65.WMVHelper
{
    public class ReaderEventArgs : EventArgs
    {
        private string _eventText;

        public ReaderEventArgs(string eventText)
        {
            _eventText = eventText;
        }

        public string ReaderEventText
        {
            get
            {
                return (_eventText);
            }
        }
    }

    public delegate void ReaderEventHandler(object sender, ReaderEventArgs e);

    public class Reader
    {
        private ThumbnailWork _thumbNailWork = new ThumbnailWork();

        public Reader()
        {
            Storage st = new Storage();
            _thumbNailWork = st.GetThumbnailWork();
        }

        public event ReaderEventHandler ReaderAlert;
        protected virtual void OnReaderAlert(ReaderEventArgs e)
        {
            if (ReaderAlert != null)
            {
                // Invokes the delegates. 
                ReaderAlert(this, e);
            }
        }


        public void AddThumbNailJob(string mediaSource, SnagItem siSource)
        {
            ThumbnailPayloadItem tp = new ThumbnailPayloadItem();
            tp.StartFrame = TimeSpan.Parse(siSource.ItemTimeSpan).Seconds + 
                (TimeSpan.Parse(siSource.ItemTimeSpan).Minutes * 60);
            tp.SourceMediaFilePath = mediaSource;
            tp.ThumbnailTargetFilePath = siSource.ThumbnailUrl;
            tp.Title = siSource.SnagName;

            _thumbNailWork.ThumbNailPayload.Add(tp);
        }

        public void AddThumbNailJob(string mediaSource, string mediaThumbnailTarget, string mediaTitle)
        {
            ThumbnailPayloadItem tp = new ThumbnailPayloadItem();
            tp.StartFrame = 0;
            tp.SourceMediaFilePath = mediaSource;
            tp.Title = mediaTitle;
            tp.ThumbnailTargetFilePath = mediaThumbnailTarget;

            _thumbNailWork.ThumbNailPayload.Add(tp);
        }

        public void PersistThumbnailWork()
        {
            try
            {
                Storage st = new Storage();
                st.PersistThumbnailWork(_thumbNailWork);
            }
            catch (SystemException se)
            {
                throw se;
            }
        }

        public void BuildThumbnails(bool extractThumbnails)
        {
            if (_thumbNailWork.ThumbNailPayload.Count > 0)
            {
                try
                {
                    Storage st = new Storage();
                    // First report back the # of thumbnails we plan to build
                    ReaderEventArgs ee = new ReaderEventArgs(String.Format("THUMB_COUNT:{0}", _thumbNailWork.ThumbNailPayload.Count));
                    OnReaderAlert(ee);

                    MediaPlayer mp = new MediaPlayer();
                    Thumbnail t = new Thumbnail(_thumbNailWork.ThumbNailPayload, mp);
                    t.ThumbnailAlert += new ThumbnailEventHandler(ThumbnailAlert);
                    bool remainingThumbs = t.BuildThumbnails(extractThumbnails);

                    if (!remainingThumbs)
                    {
                        st.RemoveThumbnailWork();
                    }
                }
                catch
                {
                    //
                }
            }
        }

        //public void PerformMaintenance()
        //{
        //    Storage st = new Storage();
        //    _thumbNailWork.ThumbNailPayload = new ArrayList();
        //    foreach (ClipShowContent target in st.GetMediaLibraries())
        //    {
        //        if (target.WatchFolders)
        //        {
        //            // First make sure we have a current list of folders
        //            if (target.WatchedFolders.Count > 0)
        //            {
        //                ClipShowContent refreshedList = new ClipShowContent();
        //                refreshedList.ContentSourceName = target.ContentSourceName;
        //                refreshedList.KeywordItems.AddRange(target.KeywordItems);
        //                refreshedList.WatchFolders = true;
        //                refreshedList.WatchedFolders.AddRange(refreshedList.WatchedFolders);

        //                foreach (string mediaDir in target.WatchedFolders)
        //                {
        //                    refreshedList.MediaItems.Add(this.CrawlDirectory(target.ContentSourceName, mediaDir, false));
        //                    this.BuildThumbnails();
        //                }

        //                refreshedList.ContentSourceName += "_1";
        //                // Now save off new playlist
        //                st.PersistMediaLibrary(refreshedList);
        //            }
        //        }
        //    }
        //}

        public void ThumbnailAlert(object sender, ThumbnailEventArgs e)
        {
            // Bubble up to parent event
            ReaderEventArgs ee = new ReaderEventArgs(e.ThumbnailEventText);
            OnReaderAlert(ee);
        }

        public MediaMetaData ReadMetaData(string filePath)
        {
            return(GetInfo(filePath));
        }

        public string GetShortCut(string linkUrl)
        {
            try
            {
                IWshRuntimeLibrary.WshShell theShell = new IWshRuntimeLibrary.WshShell();
                IWshRuntimeLibrary.WshShortcut theShortCut =
                    (IWshRuntimeLibrary.WshShortcut)theShell.CreateShortcut(linkUrl);

                return (theShortCut.TargetPath);
            }
            catch(SystemException se) 
            {
                throw (se);
            }
        }

        public ArrayList CrawlDirectory(string channelName, string directoryPath, bool recursiveCrawl)
        {
            Storage st = new Storage();
            string[] mediaTypes = st.GetSettings().AllMediaTypes;

            if (Directory.Exists(directoryPath))
            {
                ArrayList results = new ArrayList();
                if (recursiveCrawl)
                {
                    foreach (string dir in Directory.GetDirectories(directoryPath))
                    {
                        ReaderEventArgs ee = new ReaderEventArgs(String.Format("Crawling {0}", dir));
                        OnReaderAlert(ee);
                        results.AddRange(CrawlDirectory(channelName, dir, true));
                    }
                }
                foreach (string fileType in mediaTypes)
                {

                    foreach (string file in Directory.GetFiles(directoryPath,fileType))
                    {
                        if (fileType.Equals("*.lnk"))
                        {
                            try
                            {
                                IWshRuntimeLibrary.WshShell theShell = new IWshRuntimeLibrary.WshShell();
                                IWshRuntimeLibrary.WshShortcut theShortCut =
                                    (IWshRuntimeLibrary.WshShortcut)theShell.CreateShortcut(file);
                                results.AddRange(CrawlDirectory(channelName, theShortCut.TargetPath, true));
                            }
                            catch
                            {
                                // Do nothing for now, most likely reader does not have persmission to access link
                            }
                        }
                        else
                        {
                            try
                            {
                                results.Add(GetInfo(file));
                            }
                            catch (SystemException se)
                            {
                                System.Diagnostics.EventLog.WriteEntry("clipShow", se.Message);
                                ReaderEventArgs ee = new ReaderEventArgs(String.Format("Exception logged while indexing '{0}'", file));
                                OnReaderAlert(ee);
                            }
                        }
                    }
                }
                return (results);
            }
            else
            {
                return (null);
            }
        }

        public MediaMetaData GetInfo(string sourceFilePath)
        {
            MetaDataReader objMetaData = new MetaDataReader();
            MediaMetaData mt = new MediaMetaData();
            Storage st = new Storage();
            
            // If this is a dvr-ms file, use Toub wrapper
            if ( (sourceFilePath.EndsWith(".dvr-ms")) || (sourceFilePath.EndsWith(".wtv")))
            {
                AsfMetadataEditor asf = new AsfMetadataEditor(sourceFilePath, true);
                IDictionary dvrMS = asf.GetAttributes(true);

                MetadataItem title = (MetadataItem)dvrMS["Title"];
                MetadataItem description = (MetadataItem)dvrMS["WM/SubTitleDescription"];

                try
                {
                    MetadataItem origDate = (MetadataItem)dvrMS["WM/OriginalReleaseTime"];
                    if (origDate == null)
                    {
                        mt.CreationDateTime = File.GetCreationTime(sourceFilePath);
                    }
                    else
                    {
                        mt.CreationDateTime = Convert.ToDateTime((string)origDate.Value);
                        if (mt.CreationDateTime.Year < 1900)
                        {
                            mt.CreationDateTime = File.GetCreationTime(sourceFilePath);
                        }
                    }
                }
                catch
                {
                    mt.CreationDateTime = File.GetCreationTime(sourceFilePath);
                }

                try
                {
                    MetadataItem author = (MetadataItem)dvrMS["WM/MediaCredits"];
                    if (author == null)
                    {
                        mt.Author = "";
                    }
                    else
                    {
                        mt.Author = (string)author.Value;
                    }
                }
                catch
                {
                    mt.Author = "";
                }
                
                mt.Title = (string)title.Value;
                mt.Description = (string)description.Value;
                mt.Url = sourceFilePath;

                try
                {
                    Byte[] a = objMetaData.GetFieldByteArrayByName(sourceFilePath, "Duration");
                    Decimal test = Convert.ToDecimal(BitConverter.ToUInt64(a, 0));
                    mt.Duration = Convert.ToInt32(test / 10000);
                }
                catch
                {
                    mt.Duration = -1;
                }
            }
            // If this is a WMV file, process it using the wrapper
            else if (sourceFilePath.EndsWith(".wmv") )
            {
                mt.Url = sourceFilePath;
                mt.Title = ErrorCheck(objMetaData.GetFieldByName(sourceFilePath, "Title"));
                if (mt.Title.Length.Equals(0))
                {
                    mt.Title = Path.GetFileNameWithoutExtension(sourceFilePath);
                }
                mt.Author = ErrorCheck(objMetaData.GetFieldByName(sourceFilePath, "Author"));
                mt.Description = ErrorCheck(objMetaData.GetFieldByName(sourceFilePath, "Description"));
                mt.CreationDateTime = File.GetCreationTime(sourceFilePath);

                try
                {
                    Byte[] a = objMetaData.GetFieldByteArrayByName(sourceFilePath, "Duration");
                    Decimal test = Convert.ToDecimal(BitConverter.ToUInt64(a, 0));
                    mt.Duration = Convert.ToInt32(test / 10000);
                }
                catch
                {
                    mt.Duration = -1;
                }

            }
            else
            {
                // Process only the file name (mpg, mp4, mov or avi)
                mt.Title = Path.GetFileNameWithoutExtension(sourceFilePath);
                mt.Description = Path.GetFileNameWithoutExtension(sourceFilePath);
                mt.CreationDateTime = File.GetCreationTime(sourceFilePath);
                mt.Duration = -1;
                mt.Url = sourceFilePath;
            }
    
            string[] temp = mt.Url.Split('\\');
            string hashedFile = Path.GetDirectoryName(mt.Url).Replace(@"\", "_");

            string targetFile = String.Format("{0}\\{1}_{2}.jpg",
                st.GetThumbnailDir(),
                hashedFile.Replace(":", "_"),
                Path.GetFileNameWithoutExtension(mt.Url));

            if (!File.Exists(targetFile))
            {
                ThumbnailPayloadItem tp = new ThumbnailPayloadItem();
                tp.SourceMediaFilePath = mt.Url;
                tp.ThumbnailTargetFilePath = targetFile;
                tp.Title = mt.Title;
                _thumbNailWork.ThumbNailPayload.Add(tp);
            }

            mt.ThumbnailUrl = targetFile;
            return (mt);

        }

        private string ErrorCheck(string result)
        {
            if (result.StartsWith("ERROR:"))
            {
                return ("");
            }
            else
            {
                return (result);
            }
        }
    }
}
